package cn.com.aiton.common.utils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;

/**
 * JavaxXmlBind的通用工具类
 *
 * @author ParanoidCAT
 * @since JDK 1.8
 */
public class JaxbUtils {
    /**
     * 根据Jaxb注解将Java实例输出到指定的输出流中
     *
     * @param object       Java实例
     * @param outputStream 指定的输出流
     * @throws JAXBException 异常
     * @throws IOException   异常
     */
    public static void javaToXml(Object object, OutputStream outputStream) throws JAXBException, IOException {
        JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
        Marshaller marshaller = jaxbContext.createMarshaller();
        // 输出文件时编码格式
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
        // 是否格式化输出
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        // 是否输出头信息
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        marshaller.marshal(object, outputStream);
        outputStream.flush();
    }

    /**
     * 根据Jaxb注解将Java实例输出到指定的文件中
     *
     * @param object Java实例
     * @param file   指定的文件
     * @throws JAXBException 异常
     * @throws IOException   异常
     */
    public static void javaToXml(Object object, File file) throws JAXBException, IOException {
        try (OutputStream outputStream = new FileOutputStream(file)) {
            javaToXml(object, outputStream);
        }
    }

    /**
     * 根据Jaxb注解将Java实例格式化为String
     *
     * @param object Java实例
     * @return java.lang.String
     * @throws JAXBException 异常
     * @throws IOException   异常
     */
    public static String javaToXml(Object object) throws JAXBException, IOException {
        JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
        Marshaller marshaller = jaxbContext.createMarshaller();
        // 输出文件时编码格式
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
        // 是否格式化输出
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        // 是否输出头信息
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        try (StringWriter stringWriter = new StringWriter()) {
            marshaller.marshal(object, stringWriter);
            return stringWriter.toString();
        }
    }

    /**
     * 根据Jaxb注解解析输入流生成Java实例
     *
     * @param tClass      Java类的Class
     * @param inputStream 输入流
     * @param <T>         Java类
     * @return T extends Object
     * @throws JAXBException 异常
     */
    @SuppressWarnings("unchecked")
    public static <T> T xmlToJava(Class<T> tClass, InputStream inputStream) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(tClass);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        return (T) unmarshaller.unmarshal(inputStream);
    }

    /**
     * 根据Jaxb注解解析Xml文件生成Java实例
     *
     * @param tClass Java类的Class
     * @param file   Xml文件
     * @param <T>    Java类
     * @return T extends Object
     * @throws JAXBException 异常
     * @throws IOException   异常
     */
    @SuppressWarnings("unchecked")
    public static <T> T xmlToJava(Class<T> tClass, File file) throws JAXBException, IOException {
        try (InputStream inputStream = new FileInputStream(file)) {
            return xmlToJava(tClass, inputStream);
        }
    }

    /**
     * 根据Jaxb注解解析XmlString生成Java实例
     *
     * @param tClass Java类的Class
     * @param xml    XmlString
     * @param <T>    Java类
     * @return T extends Object
     * @throws JAXBException 异常
     * @throws IOException   异常
     */
    @SuppressWarnings("unchecked")
    public static <T> T xmlToJava(Class<T> tClass, String xml) throws JAXBException, IOException {
        JAXBContext jaxbContext = JAXBContext.newInstance(tClass);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        try (Reader reader = new StringReader(xml)) {
            return (T) unmarshaller.unmarshal(reader);
        }
    }

}